package de.szut.ita13.sommerfeld.loganalyser;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;

public class LogHandler {
	
	public static long timer = 0;
	public static int logcount = 0;
	public static long resourcesize = 0;
	public static int[] requests;
	public static String[] requestName = {"GET","POST","PROPFIND","HEAD","CONNECT","LOCK","UNLOCK","OPTIONS"};
	public static Log firstLog;
	public static Log lastLog;
	
	public static HashMap allUser;
	public static HashMap allResources;
	private File log;
	
	public static final int LOG_LENGTH = 10;
	public static final String[] LOG_SYNTAX = {".","[","]","\"",":"};
	
	public static final int IP_LENGTH = 4;
	public static final String IP_SYNTAX = ".";
	
	public LogHandler(File log) {
		this.log = log;
		allUser = new HashMap();
		allResources = new HashMap();
		requests = new int[requestName.length];
		for(int i = 0; i < requests.length; i++) {
			requests[i] = 0;
		}
	}

	public File getFile() {
		return log;
	}
	
	public void setFile(File log) {
		this.log = log;
	}
	
	public String getFilePath() {
		return log.getAbsolutePath();
	}
	
	public boolean fileIsLog() {
		return log.getName().endsWith(".log");
	}
	
	public boolean hasValidSignature() throws IOException, FileNotFoundException {
		boolean isValid = true;
		BufferedReader buffer = new BufferedReader(new FileReader(log.getAbsoluteFile()));
		for(int i = 0; i < LOG_SYNTAX.length; i++) {
			if(buffer.readLine() != null) {
				if(!buffer.readLine().contains(LOG_SYNTAX[i])) {
					isValid = false;
					break;
				}
			} else {
				isValid = false;
				break;
			}
		}
		boolean result = isValid && buffer.readLine().split(" ").length == LOG_LENGTH;
		buffer.close();
		return result;
	}
	
	public boolean isValidIP(String key) {
		String[] ip = key.split("\\.");
		if(ip.length == IP_LENGTH) {
			for(int i = 0; i < ip.length; i++) {
				try {
					int block = Integer.parseInt(ip[i]);
					if(block < 0 || block > 255) {
						return false;
					}
				} catch(Exception e) {
					return false;
				}
			}
			return true;
		}
		return false;
		
	}
	
	public UserSearchResultWindow searchForAnUser(String key) {
		UserSearchResultWindow usrw = null;
		if(isValidIP(key)) {
			User user = (User)allUser.get(key);
			if(user == null) {
				usrw = new UserSearchResultWindow(key, "IP " + key + " DOESNT EXIST IN LOG!");
			} else if(user.getLogs().size() > 0) {
				usrw = new UserSearchResultWindow(key, user);
			}
		} else {
			usrw = new UserSearchResultWindow(key, "USER DOESNT EXIST IN LOG!");
		}
		return usrw;
	}
	
	public ApacheLog analyseLog() throws IOException, FileNotFoundException {
		ArrayList stats = new ArrayList();
		timer = System.currentTimeMillis();
		Scanner buffer = new Scanner(new BufferedReader(new FileReader(log.getAbsoluteFile())));
		while(buffer.hasNextLine()) {
			logcount++;
			String logline = buffer.nextLine();
			String ip = logline.split(" ")[0];
			User newUser = new User(ip);
			Log parsedLog = LogLineParser.parseLineToLog(logline);
			if(parsedLog != null) {
				String resource = parsedLog.getResource();
				if(!allResources.containsKey(resource)) {
					allResources.put(resource, new Resource(resource,0));
				} else if(allResources.containsKey(resource)) {
					Resource res = (Resource)allResources.get(resource);
					res.incrementCounter();
				}
			}
			if(!allUser.containsKey(ip)) {
				if(LogLineParser.lineAvailable(logline)) {
					newUser.getLogs().add(parsedLog);
					newUser.setFirstAction(parsedLog.getDate());
					newUser.addResourceSize(parsedLog.getSize());
					resourcesize += parsedLog.getSize();
					for(int i = 0; i < requests.length; i++) {
						if(parsedLog.getResource().contains(requestName[i])) {
							requests[i]++;
							break;
						}
					}
					allUser.put(ip, newUser);
				}
			} else {
				User currentUser = (User) allUser.get(ip);
				if(LogLineParser.lineAvailable(logline)) {
					resourcesize += parsedLog.getSize();
					for(int i = 0; i < requests.length; i++) {
						if(parsedLog.getResource().contains(requestName[i])) {
							requests[i]++;
							break;
						}
					}
					currentUser.getLogs().add(parsedLog);
					currentUser.addResourceSize(parsedLog.getSize());
					currentUser.setLastAction(parsedLog.getDate());
				}
			}
			if(logcount == 1)
				firstLog = parsedLog;	
			if(LogLineParser.lineAvailable(logline)) {
				lastLog = parsedLog;
			}
		}
		buffer.close();
		stats.add(String.valueOf(logcount));
		stats.add(String.valueOf(allResources.size()));
		stats.add(String.valueOf(resourcesize));
		stats.add(String.valueOf(allUser.size()));
		stats.add(firstLog.getDateString());
		stats.add(lastLog.getDateString());
			
		stats.add(String.valueOf(System.currentTimeMillis() - timer));
		for(int i = 0; i < requests.length; i++) {
			stats.add(String.valueOf(requests[i]));
		}
		
		ApacheLog apachelog = new ApacheLog(log.getName(), log, stats);
		
		return apachelog;
	}
}
